home *** CD-ROM | disk | FTP | other *** search
- /************************************************************************/
- /* */
- /* Source - Calendar.c */
- /* Author - Alexander S. Colwell, Copyright © 1990 */
- /* */
- /* Purpose - This is external area to display an calendar. */
- /* */
- /* Notes - The text strings must be drawn before line separatars, */
- /* because 4th Dimension has patched the "DrawString" and */
- /* "DrawChar" in a way that it erases additional pixels */
- /* above the characters. This problem does not occurs in the*/
- /* "4th Debugger". */
- /* */
- /************************************************************************/
-
- #include "Calendar.h" /* Calendar defs */
-
- C4th *New(void) { return(new(CCalendar)); }/*Calendar obj allocator */
-
- void CCalendar::IExtArea(short getKeyBoard)
- {
- Rect wRect; /* Working rect area */
-
- inherited::IExtArea(TRUE); /* Do other initialization */
-
- month = 1; /* Set "January" default */
- year = 1990; /* Set 1990 year default */
- daySelect = 0L; /* Set no selected days */
- dayIndex = GetDayIndex(); /* Set "day" offset */
-
- nextMonth = NewRgn(); /* Allocate next button region */
- prevMonth = NewRgn(); /* Allocate previous button region */
- }
-
- void CCalendar::Close(void)
- {
- if (nextMonth) /* Check if region handle is valid */
- DisposeRgn(nextMonth); /* Release this region handle */
- nextMonth = NULL; /* Invalidate the region handle */
-
- if (prevMonth) /* Check if region handle is valid */
- DisposeRgn(prevMonth);/* Release this region handle */
- prevMonth = NULL; /* Invalidate the region handle */
-
- inherited::Close(); /* Continue closing */
- }
-
- void CCalendar::Cursor(Point pt) /* Cursor over external area method */
- {
- register short i; /* Working index */
- register short days; /* Working number of days per month */
- register short doIt = FALSE;/* Working status indicator */
- Rect wRect; /* Working day area */
-
- if (nextMonth) /* Check if "next" button region valid*/
- if (PtInRgn(pt,nextMonth))/* Check if inside this region */
- doIt = TRUE; /* Let's do it */
-
- if (!doIt) /* Check if should continue */
- if (prevMonth) /* Check if "prev" button region valid*/
- if (PtInRgn(pt,prevMonth))/* Check if inside this region*/
- doIt = TRUE; /* Let's do it */
-
- if (!doIt) { /* Check if should continue */
- days = GetDays(); /* Get number of days for this month*/
- for(i = 1; i <= days; i++) {/* Search for selected day */
- DayRect(&wRect,GetRowIndex(i),GetColumnIndex(i));
- if (PtInRect(pt,&wRect)) {/* Check if point inside day */
- doIt = TRUE; /* Let's do it */
- break; /* Break-out of da loop! */
- }
- }
- }
-
- if (doIt) /* Check if want to do it */
- inherited::Cursor(pt); /* OK, let do standard cursor */
- else /* Nope, let's not do it */
- InitCursor(); /* Reset to arrow cursor */
- }
-
- void CCalendar::SetupValues(void)
- {
- dayWidth = width / 7; /* Compute aveage day width */
- dayHeight = (height - headerHeight) / 7;/* Compute ave day height*/
- }
-
- void CCalendar::Draw(void)
- {
- register short i; /* Working index */
- register short days; /* Working number of days per month */
- register short usingColor; /* Working using color indicator */
- Str255 label; /* Working label string */
- Rect wRect; /* Working rect area */
- RGBColor saveColor; /* Working save fore-ground color */
- register RgnHandle wRgn; /* Working region handle */
-
- TextFont(geneva); /* Set to "Geneva" font */
- TextSize(9); /* Set to 9-point font */
- TextFace(0); /* Set to "plain" text */
-
- wRect = drawArea; /* Setup drawing area */
-
- EraseRect(&wRect); /* Clear-out old stuff */
- FrameRect(&wRect); /* Frame da calendar */
-
- SetupValues(); /* Setup working values */
-
- switch(month) { /* Copy month to label */
- case 1: BlockMove("\pJanuary ",label,9L); break;
- case 2: BlockMove("\pFeburary ",label,10L); break;
- case 3: BlockMove("\pMarch ",label,7L); break;
- case 4: BlockMove("\pApril ",label,7L); break;
- case 5: BlockMove("\pMay ",label,5L); break;
- case 6: BlockMove("\pJune ",label,6L); break;
- case 7: BlockMove("\pJuly ",label,6L); break;
- case 8: BlockMove("\pAugust ",label,8L); break;
- case 9: BlockMove("\pSeptember ",label,11L); break;
- case 10: BlockMove("\pOctober ",label,9L); break;
- case 11: BlockMove("\pNovember ",label,10L); break;
- case 12: BlockMove("\pDecember ",label,10L); break;
- }
-
- /* Concat year */
- NumToString((long)(year),&label[128]);
- BlockMove(&label[129],&label[label[0]+1],(long)(label[128]));
- label[0] += label[128];
-
- DrawDay((char *)(label),0,4);/* Draw Month/Year label */
-
- DrawDay("\pS",1,1); /* Draw "Week Day" labels */
- DrawDay("\pM",1,2);
- DrawDay("\pT",1,3);
- DrawDay("\pW",1,4);
- DrawDay("\pT",1,5);
- DrawDay("\pF",1,6);
- DrawDay("\pS",1,7);
-
- days = GetDays(); /* Get number of days for this month*/
- for(i = 1; i <= days; i++) {/* Draw "Day" labels */
- NumToString((long)(i),label);
- DrawDay((char *)(label),GetRowIndex(i),GetColumnIndex(i));
- }
-
- if (active || !tmpRgn) { /* Check if field is active */
- for(i = 1; i <= days; i++)/* Hilite the days */
- if (daySelect & (1L << (long)(i - 0)))
- HiliteDay(GetRowIndex(i),GetColumnIndex(i));
- }
- else { /* Nope, let's frame it */
- MakeDayOutline(); /* Make day's outline */
- if (wRgn = NewRgn()) { /* Check if got region handle */
- CopyRgn(tmpRgn,wRgn);/* Copy the outline region handle */
- InsetRgn(wRgn,1,1); /* Shrink it a bit */
- DiffRgn(tmpRgn,wRgn,tmpRgn);/* OK, let's get difference */
- DisposeRgn(wRgn); /* Release working region */
- HiliteMode &= 0x7f; /* Set highliting bit */
- InvertRgn(tmpRgn); /* Outline the days by inverting */
- }
- else { /* Nope, do it less sub-optimal way */
- if (usingColor = UsingColor()) {/* Check if using color */
- GetForeColor(&saveColor);/* Save fore-ground color */
- RGBForeColor(&HiliteRGB);/* Set hilite's fore color */
- }
- FrameRgn(tmpRgn); /* Outline the days */
- if (usingColor) /* Check if using color */
- RGBForeColor(&saveColor);/* Restore fore color */
- }
- }
-
- /* Draw separators */
- MoveTo(drawArea.left,drawArea.top + headerHeight);
- LineTo(drawArea.left + width,drawArea.top + headerHeight);
- MoveTo(drawArea.left,drawArea.top + dayHeight + headerHeight);
- LineTo(drawArea.left + width,drawArea.top + dayHeight + headerHeight);
-
- if (prevMonth) { /* Check if region handle is valid */
- if (EmptyRgn(prevMonth)) {/* Check if empty to be drawn */
- OpenRgn(); /* Start button drawing */
- MoveTo(drawArea.left+3,drawArea.top+headerHeight/2+1);
- LineTo(drawArea.left+headerHeight/2+2,drawArea.top+1);
- LineTo(drawArea.left+headerHeight/2+2,drawArea.top+headerHeight/4+1);
- LineTo(drawArea.left+headerHeight-headerHeight/6,
- drawArea.top+headerHeight/4+1);
- LineTo(drawArea.left+headerHeight-headerHeight/6,
- drawArea.top+headerHeight-headerHeight/4);
- LineTo(drawArea.left+headerHeight/2+2,
- drawArea.top+headerHeight-headerHeight/4);
- LineTo(drawArea.left+headerHeight/2+2,drawArea.top+headerHeight-1);
- LineTo(drawArea.left+3,drawArea.top+headerHeight/2+1);
- CloseRgn(prevMonth);/* Close button drawing */
- }
- if (layout || active) /* Check if should draw button */
- FrameRgn(prevMonth);/* Draw "previous" button */
- }
-
- if (nextMonth) { /* Check if region handle is valid */
- if (EmptyRgn(nextMonth)) {/* Check if empty to be drawn */
- OpenRgn(); /* Start button drawing */
- MoveTo(drawArea.right-3,drawArea.top+headerHeight/2+1);
- LineTo(drawArea.right-headerHeight/2-2,drawArea.top+2);
- LineTo(drawArea.right-headerHeight/2-2,drawArea.top+headerHeight/4+1);
- LineTo(drawArea.right-headerHeight+headerHeight/6,
- drawArea.top+headerHeight/4+1);
- LineTo(drawArea.right-headerHeight+headerHeight/6,
- drawArea.top+headerHeight-headerHeight/4);
- LineTo(drawArea.right-headerHeight/2-2,
- drawArea.top+headerHeight-headerHeight/4);
- LineTo(drawArea.right-headerHeight/2-2,drawArea.top+headerHeight-1);
- LineTo(drawArea.right-3,drawArea.top+headerHeight/2+1);
- CloseRgn(nextMonth);/* Close button drawing */
- }
- if (layout || active) /* Check if should draw button */
- FrameRgn(nextMonth);/* Draw "next" button */
- }
- }
-
- void CCalendar::DrawDay(char *label, short row, short column)
- {
- FontInfo fontInfo; /* Working font information */
- Rect wRect; /* Working rect area */
-
- DayRect(&wRect,row,column); /* Get day rect area */
-
- GetFontInfo(&fontInfo); /* Get current font information */
-
- /* Position da string */
- MoveTo(wRect.left + dayWidth / 2 - StringWidth(label) / 2,
- wRect.top + ((row ? dayHeight : headerHeight) -
- fontInfo.ascent - fontInfo.descent) / 2 + fontInfo.ascent);
-
- DrawString(label); /* Draw the string label */
- }
-
- void CCalendar::HiliteDay(short row, short column)
- {
- Rect wRect; /* Working rect area */
-
- DayRect(&wRect,row,column); /* Get day rect area */
- HiliteMode &= 0x7f; /* Set highliting bit */
- InvertRect(&wRect); /* Invert it */
- }
-
- void CCalendar::DayRect(Rect *rect, short row, short column)
- {
- rect->left = rect->top = 0; /* Set relative day rect area */
- rect->right = dayWidth;
- rect->bottom = dayHeight;
-
- /* Offset the day for drawing */
- OffsetRect(rect,dayWidth * (column - 1) + drawArea.left,
- dayHeight * row +
- (row ? max(0,headerHeight - dayHeight) : 0) +
- drawArea.top);
- }
-
- short CCalendar::MakeDayOutline(void)
- {
- register short i; /* Working index */
- register short days; /* Working number of days per month */
- Rect wRect; /* Working rect area */
- register short status = FALSE;/* Working status indicator */
-
- if (tmpRgn) { /* Check if it's valid */
- days = GetDays(); /* Get number of days for this month*/
- EmptyRgn(tmpRgn); /* Set region empty for day framing */
- OpenRgn(); /* Start region drawing */
- for(i = 1; i <= days; i++)/* Outline the days */
- if (daySelect & (1L << (long)(i - 0))) {/* Selected day?*/
- status = TRUE; /* Mark days has some outlining */
- DayRect(&wRect,GetRowIndex(i),GetColumnIndex(i));
- FrameRect(&wRect);
- }
- CloseRgn(tmpRgn); /* Copy da region */
- }
-
- return(status); /* Return any days for outlining */
- }
-
- void CCalendar::Select(void)
- {
- inherited::Select(); /* Do other stuff first */
- if (MakeDayOutline()) { /* Make day's outline */
- InsetRgn(tmpRgn,1,1); /* Shrink it a bit */
- HiliteMode &= 0x7f; /* Set highliting bit */
- InvertRgn(tmpRgn); /* Invert region */
- }
- if (nextMonth) /* Check if has "next" month button */
- InvalRgn(nextMonth); /* Invalidate it */
- if (prevMonth) /* Check if has "prev" month button */
- InvalRgn(prevMonth); /* Invalidate it */
- }
-
- void CCalendar::Deselect(void)
- {
- inherited::Deselect(); /* Do other stuff first */
- if (MakeDayOutline()) { /* Make day's outline */
- InsetRgn(tmpRgn,1,1); /* Shrink it a bit */
- HiliteMode &= 0x7f; /* Set highliting bit */
- InvertRgn(tmpRgn); /* Invert region */
- }
- if (nextMonth) /* Check if has "next" month button */
- InvalRgn(nextMonth); /* Invalidate it */
- if (prevMonth) /* Check if has "prev" month button */
- InvalRgn(prevMonth); /* Invalidate it */
- }
-
- void CCalendar::Scroll(void)
- {
- if (nextMonth) /* Check if got "next" region handle*/
- OffsetRgn(nextMonth,drawArea.left - prevArea.left,
- drawArea.top - prevArea.top);
-
- if (prevMonth) /* Check if got "prev" region handle*/
- OffsetRgn(prevMonth,drawArea.left - prevArea.left,
- drawArea.top - prevArea.top);
- }
-
- void CCalendar::DoClick(Point pt, short modifiers, long ticks)
- {
- register short i; /* Working index */
- register short lastDay = 0;/* Working last day selected */
- register short days; /* Working number of days per month */
- register short hiliteMode = TRUE;/* Working hilite mode */
- register unsigned long mask;/* Working mask */
- short row; /* Working row day position */
- short column; /* Working column day position */
- Rect wRect; /* Working rect area */
-
- if (nextMonth) { /* Check if selecting "next" month */
- if (TrackMouse(pt,nextMonth)) {/* Track da mouse!! */
- daySelect = 0L; /* Zap current selection */
- month += 1; /* Go to next month */
- if (month == 13) { /* Check if it's into next year */
- month = 1; /* Reset to "January" */
- year += 1; /* Re-draw the calendar */
- }
- dayIndex = GetDayIndex();/* Set "day" offset */
- Draw(); /* Re-draw the calendar */
- }
- }
-
- if (prevMonth) { /* Check if selecting "previous" month*/
- if (TrackMouse(pt,prevMonth)) {/* Still selecting? */
- daySelect = 0L; /* Zap current selection */
- month -= 1; /* Go to previous month */
- if (month == 0) { /* Check if it's into previous year */
- month = 12; /* Reset to "Decemeber" */
- year -= 1; /* Go to previous year */
- }
- dayIndex = GetDayIndex();/* Set "day" offset */
- Draw(); /* Re-draw the calendar */
- }
- }
-
- days = GetDays(); /* Get number of days for this month*/
-
- do { /* Track da mouse!! */
- for(i = 1; i <= days; i++) {/* Search for selected day */
- DayRect(&wRect,row = GetRowIndex(i),
- column = GetColumnIndex(i));
- if (PtInRect(pt,&wRect)) {/* Check if point inside day */
- mask = (1L << (long)(i - 0));/* Set mask */
- if (!lastDay) { /* Check if first time */
- if (daySelect & mask)/* Check if hilited */
- hiliteMode = FALSE;/* Reset to hiliting mode*/
- }
- if (lastDay != i) {/* Check if it's new day */
- if (hiliteMode) {/* Check if hiliting the days */
- if (!(daySelect & mask)) {/* Not selected ? */
- HiliteDay(row,column);/* Hilite day */
- daySelect ^= mask;/* Set this day */
- }
- }
- else { /* Nope, unhiliting the days */
- if (daySelect & mask) {/* Selected ? */
- HiliteDay(row,column);/* Unhilite day */
- daySelect ^= mask;/* Clear this day */
- }
- }
- }
- lastDay = i; /* Save last selected day */
- }
- }
- GetMouse(&pt); /* Get next mouse position */
- } while(Button()); /* Track while mouse is down */
- }
-
- short CCalendar::GetDays(void)
- {
- register short days; /* Working number of days */
- static short monthDays[] = {31,28,31,30,31,30,31,31,30,31,30,31};
-
- if ((days = monthDays[month - 1]) == 28)/* Check if "Feburary" */
- days += LeapYear(); /* Add leap year day */
-
- return(days); /* Return number of days */
- }
-
- short CCalendar::GetDayIndex(void)
- {
- DateTimeRec dateTime; /* Working date/time stamp */
- long secs; /* Working seconds */
-
- dateTime.year = year; /* Init date/time stamp */
- dateTime.month = month;
- dateTime.day = 1;
- dateTime.hour = 0;
- dateTime.minute = 0;
- dateTime.second = 0;
-
- Date2Secs(&dateTime,&secs); /* Translate to seconds */
- Secs2Date(secs,&dateTime); /* Convert it back to get day of week*/
-
- return(dateTime.dayOfWeek - 1);/* Return day of the week */
- }
-
- short CCalendar::GetRowIndex(short idx)
- { return(2 + ((idx - 1 + dayIndex) / 7)); }
-
- short CCalendar::GetColumnIndex(short idx)
- { return(1 + ((idx - 1 + dayIndex) % 7)); }
-
- short CCalendar::LeapYear(void)
- {
- DateTimeRec dateTime; /* Working date/time stamp */
- long secs; /* Working seconds */
- register short leapDay = 0;/* Working leap year day */
-
- dateTime.year = year; /* Init date/time stamp */
- dateTime.month = month;
- dateTime.day = 29;
- dateTime.hour = 0;
- dateTime.minute = 0;
- dateTime.second = 0;
-
- Date2Secs(&dateTime,&secs); /* Translate to seconds */
- Secs2Date(secs,&dateTime); /* Convert it back to get day of week*/
-
- if (dateTime.day == 29) /* Check if it's still same day */
- leapDay = 1; /* Yup, it's leap year!!!! */
-
- return(leapDay); /* Return leap year day */
- }
-